import matplotlib.pyplot as plt  # 绘制图形
import pandas as pd  # 处理数据
from sklearn.ensemble import RandomForestClassifier  # 构建随机森林分类器
from sklearn.metrics import accuracy_score, recall_score, f1_score, confusion_matrix  # 导入准确率、召回率、F1 分数和混淆矩阵的计算函数
from sklearn.model_selection import train_test_split  # 将数据集划分为训练集和测试集


def data_analysis(df):
    """
    对给定的数据集进行数据分析，包括数据集的处理、用户流失特征提取、模型选择和构建、流失预测和标签分类、结果分析和可视化。

    参数：
    df (pd.DataFrame): 包含数据的 DataFrame。

    返回：
    None
    """
    # 数据集的处理
    df = df.dropna(axis=0, how='any')  # 删除空值
    df['Churn'] = df['Churn'].astype(int)  # 将 Churn 列转换为整数类型

    # 将性别属性转换为 0 和 1，女性为0，男性为1
    df['Gender'] = pd.factorize(df['Gender'])[0]  # 将分类变量转换为整数类型

    # 用户流失特征提取
    features = df[['Tenure', 'WarehouseToHome', 'AgeGroup', 'Gender', 'HourSpendOnApp', 'OrderCount',
                   'OrderAmountHikeFromlastYear', 'DaySinceLastOrder', 'CouponUsed', 'NumberOfStreamerFollowed',
                   'SatisfactionScore', 'DiscountAmount']]
    target = df['Churn']

    # 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)

    # 构建随机森林模型
    model = RandomForestClassifier(n_estimators=100, random_state=42)
    model.fit(X_train, y_train)

    # 进行流失预测和标签分类
    y_pred = model.predict(X_test)

    # 计算准确率
    accuracy = round(accuracy_score(y_test, y_pred) * 100, 2)
    print('Accuracy:', accuracy)

    # 计算召回率
    recall = round(recall_score(y_test, y_pred) * 100, 2)
    print('Recall:', recall)

    # 计算 F1 分数
    f1 = round(f1_score(y_test, y_pred) * 100, 2)
    print('F1 score:', f1)

    # 绘制混淆矩阵
    confusion_matrix(y_test, y_pred)
    plt.show()

    # 绘制 ROC 曲线
    from sklearn.metrics import roc_curve, roc_auc_score
    y_prob = model.predict_proba(X_test)[:, 1]
    fpr, tpr, _ = roc_curve(y_test, y_prob)
    roc_auc = roc_auc_score(y_test, y_prob)
    plt.figure()
    plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
    plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.05])
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.title('Receiver Operating Characteristic')
    plt.legend(loc="lower right")
    plt.show()

    # 绘制特征重要性
    from sklearn.ensemble import RandomForestRegressor
    importance = RandomForestRegressor().fit(X_train, y_train).feature_importances_
    importance_df = pd.DataFrame({'Feature': features.columns, 'Importance': importance})
    importance_df = importance_df.sort_values('Importance', ascending=False)
    plt.bar(importance_df['Feature'], importance_df['Importance'])
    plt.xlabel('Feature')
    plt.ylabel('Importance')
    plt.title('Feature Importance')
    plt.show()

    # 系统实现和界面设计（略）

    # 系统测试和优化（略）


# 加载数据集
df = pd.read_excel('E:\桌面\大四\毕设\Project Dataset.xlsx', sheet_name='E Comm')

# 进行数据分析
data_analysis(df)
